package com.example.surfaceview_textureview.camera;

import android.Manifest;
import android.content.pm.PackageManager;

import android.hardware.Camera;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.media.MediaMuxer;
import android.os.Bundle;
import android.os.Environment;
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
import android.widget.Button;

import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import com.example.surfaceview_textureview.R;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.concurrent.LinkedBlockingQueue;

public class CameraActivity extends AppCompatActivity {
    private static final int REQUEST_CAMERA_PERMISSION = 200;
    private TextureView textureView;
    private Button btnStartRecording;
    private Camera camera;
    private MediaCodec encoder;
    private MediaMuxer muxer;
    private Surface encoderSurface;
    private boolean isRecording = false;
    private int videoTrackIndex = -1;
    private LinkedBlockingQueue<byte[]> frameQueue = new LinkedBlockingQueue<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this);
        setContentView(R.layout.activity_camera);
        textureView = findViewById(R.id.textureView);
        btnStartRecording = findViewById(R.id.btnStartRecording);
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CAMERA_PERMISSION);
        } else {
            startCamera();
        }

        btnStartRecording.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (!isRecording) {
                    startRecording();
                } else {
                    stopRecording();
                }
            }
        });
    }

    private void startCamera() {
        camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
        try {
            camera.setPreviewCallback(new Camera.PreviewCallback() {
                @Override
                public void onPreviewFrame(byte[] data, Camera camera) {

                }
            });
            camera.setPreviewTexture(textureView.getSurfaceTexture());
            camera.startPreview();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void startRecording() {
        isRecording = true;
        btnStartRecording.setText("停止录制");

        try {
            // 创建编码器
            MediaFormat format = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, 1280, 720);
            format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
            format.setInteger(MediaFormat.KEY_BIT_RATE, 5000000); //码率
            format.setInteger(MediaFormat.KEY_FRAME_RATE, 30); //帧率
            format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 2); //关键帧间隔

            encoder = MediaCodec.createEncoderByType(MediaFormat.MIMETYPE_VIDEO_AVC); //H264编码
            encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
            encoderSurface = encoder.createInputSurface();
            encoder.start();
            //创建混合器
            muxer = new MediaMuxer(Environment.getExternalStorageDirectory().getPath() + "/output.mp4", MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);

            new Thread(new EncoderThread()).start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private class EncoderThread implements Runnable {
        @Override
        public void run() {
            try {
                MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();

                while (isRecording) {
                    int outputBufferIndex = encoder.dequeueOutputBuffer(bufferInfo, 10000);
                    if (outputBufferIndex >= 0) {
                        ByteBuffer outputBuffer = encoder.getOutputBuffer(outputBufferIndex);
                        if (videoTrackIndex == -1) {
                            videoTrackIndex = muxer.addTrack(encoder.getOutputFormat());
                            muxer.start();
                        }
                        muxer.writeSampleData(videoTrackIndex, outputBuffer, bufferInfo);
                        encoder.releaseOutputBuffer(outputBufferIndex, false);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }




}